package com.hippo.module.sys.service.impl;



import com.hippo.api.sys.entity.*;
import com.hippo.common.base.util.ArithUtil;
import com.hippo.common.base.util.ByteUtil;
import com.hippo.common.base.util.IPUtil;
import com.hippo.module.sys.service.SysInfoService;
import org.springframework.stereotype.Service;
import oshi.SystemInfo;
import oshi.hardware.CentralProcessor;
import oshi.hardware.GlobalMemory;
import oshi.hardware.HardwareAbstractionLayer;
import oshi.software.os.FileSystem;
import oshi.software.os.OSFileStore;
import oshi.software.os.OperatingSystem;
import oshi.util.Util;

import java.util.*;

@Service
public class SysInfoServiceImpl implements SysInfoService {

    private static final int OSHI_WAIT_SECOND = 1000;

    public Map<String, Object> querySysInfo() throws Exception {
        SystemInfo si = new SystemInfo();
        HardwareAbstractionLayer hal = si.getHardware();

        Map<String, Object> map = new HashMap<>();
        map.put("cpuInfo", this.setCpuInfo(hal.getProcessor()));
        map.put("memoryInfo", this.setMemoryInfo(hal.getMemory()));
        map.put("computerInfo", this.setComputerInfo());
        map.put("jvmInfo", this.setJvmInfo());
        map.put("diskInfo", this.setDiskInfo(si.getOperatingSystem()));
        return map;
    }

    /**
     * 设置cpu信息
     *
     * @param processor
     * @return
     */
    private CpuInfoEntity setCpuInfo(CentralProcessor processor) {
        // CPU信息
        long[] prevTicks = processor.getSystemCpuLoadTicks();
        Util.sleep(OSHI_WAIT_SECOND);
        long[] ticks = processor.getSystemCpuLoadTicks();
        long nice = ticks[CentralProcessor.TickType.NICE.getIndex()] - prevTicks[CentralProcessor.TickType.NICE.getIndex()];
        long irq = ticks[CentralProcessor.TickType.IRQ.getIndex()] - prevTicks[CentralProcessor.TickType.IRQ.getIndex()];
        long softirq = ticks[CentralProcessor.TickType.SOFTIRQ.getIndex()] - prevTicks[CentralProcessor.TickType.SOFTIRQ.getIndex()];
        long steal = ticks[CentralProcessor.TickType.STEAL.getIndex()] - prevTicks[CentralProcessor.TickType.STEAL.getIndex()];
        long cSys = ticks[CentralProcessor.TickType.SYSTEM.getIndex()] - prevTicks[CentralProcessor.TickType.SYSTEM.getIndex()];
        long user = ticks[CentralProcessor.TickType.USER.getIndex()] - prevTicks[CentralProcessor.TickType.USER.getIndex()];
        long iowait = ticks[CentralProcessor.TickType.IOWAIT.getIndex()] - prevTicks[CentralProcessor.TickType.IOWAIT.getIndex()];
        long idle = ticks[CentralProcessor.TickType.IDLE.getIndex()] - prevTicks[CentralProcessor.TickType.IDLE.getIndex()];
        long totalCpu = user + nice + cSys + idle + iowait + irq + softirq + steal;

        CpuInfoEntity cpuInfo = new CpuInfoEntity();
        cpuInfo.setCpuNum(processor.getLogicalProcessorCount());
        cpuInfo.setTotal(totalCpu);
        cpuInfo.setSys(cSys);
        cpuInfo.setUsed(user);
        cpuInfo.setWait(iowait);
        cpuInfo.setFree(idle);
        return cpuInfo;
    }

    /**
     * 设置内存信息
     */
    private MemoryInfoEntity setMemoryInfo(GlobalMemory memory) {
        MemoryInfoEntity memoryInfo = new MemoryInfoEntity();
        memoryInfo.setTotal(memory.getTotal());
        memoryInfo.setUsed(memory.getTotal() - memory.getAvailable());
        memoryInfo.setFree(memory.getAvailable());
        return memoryInfo;
    }

    /**
     * 设置服务器信息
     */
    private ComputerInfoEntity setComputerInfo() {
        ComputerInfoEntity computerInfo = new ComputerInfoEntity();
        Properties props = System.getProperties();
        computerInfo.setComputerName(IPUtil.getHostName());
        computerInfo.setComputerIp(IPUtil.getHostIp());
        computerInfo.setOsName(props.getProperty("os.name"));
        computerInfo.setOsArch(props.getProperty("os.arch"));
        computerInfo.setUserDir(props.getProperty("user.dir"));
        return computerInfo;
    }

    /**
     * 设置Java虚拟机信息
     */
    private JvmInfoEntity setJvmInfo() {
        JvmInfoEntity jvmInfo = new JvmInfoEntity();
        Properties props = System.getProperties();
        jvmInfo.setTotal(Runtime.getRuntime().totalMemory());
        jvmInfo.setMax(Runtime.getRuntime().maxMemory());
        jvmInfo.setFree(Runtime.getRuntime().freeMemory());
        jvmInfo.setVersion(props.getProperty("java.version"));
        jvmInfo.setHome(props.getProperty("java.home"));
        return jvmInfo;
    }

    /**
     * 设置磁盘信息
     */
    private List<DiskInfoEntity> setDiskInfo(OperatingSystem os) {
        List<DiskInfoEntity> diskInfoList = new ArrayList<>();
        FileSystem fileSystem = os.getFileSystem();
        List<OSFileStore> fileStoreList = fileSystem.getFileStores();
        for (OSFileStore fs : fileStoreList) {
            long free = fs.getUsableSpace();
            long total = fs.getTotalSpace();
            long used = total - free;
            DiskInfoEntity diskInfo = new DiskInfoEntity();
            diskInfo.setDirName(fs.getMount());
            diskInfo.setSysTypeName(fs.getType());
            diskInfo.setTypeName(fs.getName());
            diskInfo.setTotal(ByteUtil.convertSizeToStr(total));
            diskInfo.setFree(ByteUtil.convertSizeToStr(free));
            diskInfo.setUsed(ByteUtil.convertSizeToStr(used));
            diskInfo.setUsage(ArithUtil.mul(ArithUtil.div(used, total, 4), 100));
            diskInfoList.add(diskInfo);
        }

        return diskInfoList;
    }
}
